package com.ruoyi.web.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.web.domain.DeviceAccessVisitor;
import com.ruoyi.web.domain.MonitorArea;
import com.ruoyi.web.domain.dto.DeviceAccessVisitorDto;
import com.ruoyi.web.mapper.DeviceAccessVisitorMapper;
import com.ruoyi.web.service.IDeviceAccessVisitorService;
import com.ruoyi.web.service.IMonitorAreaService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DeviceAccessVisitorServiceImpl extends ServiceImpl<DeviceAccessVisitorMapper, DeviceAccessVisitor> implements IDeviceAccessVisitorService {

    @Resource
    private DeviceAccessVisitorMapper deviceAccessVisitorMapper;
    @Autowired
    private IMonitorAreaService areaService;

    @Override
    public List<DeviceAccessVisitor> selectByCondition(DeviceAccessVisitor condition) {
        Long userId = SecurityUtils.getUserId();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        List<SysRole> roles = user.getRoles();
        if(roles != null){
            List<Long> roleIds = roles.stream().map(SysRole::getRoleId).collect(Collectors.toList());
            if(roleIds.contains(1L)){
                //管理员
                condition.setAdminFlag("1");
            }else{
                condition.setAdminFlag("0");
                condition.setSubmitUserId(userId);
            }
        }else{
            condition.setAdminFlag("0");
            condition.setSubmitUserId(userId);
        }
        return deviceAccessVisitorMapper.selectByCondition(condition);
    }

    @Override
    public List<DeviceAccessVisitor> selectDistinctByCode(DeviceAccessVisitor condition) {
        Long userId = SecurityUtils.getUserId();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        List<SysRole> roles = user.getRoles();
        if(roles != null){
            List<Long> roleIds = roles.stream().map(SysRole::getRoleId).collect(Collectors.toList());
            if(roleIds.contains(1L)){
                //管理员
                condition.setAdminFlag("1");
            }else{
                condition.setAdminFlag("0");
                condition.setSubmitUserId(userId);
            }
        }else{
            condition.setAdminFlag("0");
            condition.setSubmitUserId(userId);
        }
        return deviceAccessVisitorMapper.selectDistinctByCode(condition);
    }

    @Override
    public List<DeviceAccessVisitor> pageList(Page page, DeviceAccessVisitor condition) {
        return deviceAccessVisitorMapper.pageList(page, condition);
    }

    @Override
    public DeviceAccessVisitor detail(Long baseId) {
        return deviceAccessVisitorMapper.selectById(baseId);
    }

    @Override
    public int insertRecord(DeviceAccessVisitor visitor) {
        return deviceAccessVisitorMapper.insert(visitor);
    }

    @Override
    public synchronized int recordVisitor(DeviceAccessVisitor visitor) {
        String ipAddress = visitor.getIpAddress();
        String accessCode = visitor.getAccessCode();
        String deviceId = visitor.getDeviceId();
        if("0".equals(visitor.getOnlineFlag()) && "1".equals(visitor.getType())){
            List<DeviceAccessVisitor> visitList = this.list(new LambdaQueryWrapper<DeviceAccessVisitor>()
                    .eq(DeviceAccessVisitor::getIpAddress, ipAddress).eq(DeviceAccessVisitor::getOnlineFlag, "1")
                    .eq(DeviceAccessVisitor::getAccessCode, accessCode));
            if(!CollectionUtils.isEmpty(visitList)){
                for (DeviceAccessVisitor deviceAccessVisitor : visitList) {
                    Date beginTime = deviceAccessVisitor.getBeginTime();
                    Date endTime = new Date();
                    deviceAccessVisitor.setEndTime(endTime);
                    deviceAccessVisitor.setOnlineFlag("0");
                    Duration duration = Duration.ofMillis(endTime.getTime() - beginTime.getTime());
                    long seconds = duration.getSeconds();
                    deviceAccessVisitor.setAccessInterval(seconds);
                    deviceAccessVisitor.setUpdateTime(endTime);

                }
                this.updateBatchById(visitList);
                return 0;
            }


        }
        List<DeviceAccessVisitor> list;
        if("0".equals(visitor.getType())){
            list = this.list(new LambdaQueryWrapper<DeviceAccessVisitor>()
                    .eq(DeviceAccessVisitor::getIpAddress, ipAddress).eq(DeviceAccessVisitor::getDeviceId, deviceId).eq(DeviceAccessVisitor::getOnlineFlag, "1")
                    .eq(DeviceAccessVisitor::getAccessCode, accessCode));
        }else{
            list = this.list(new LambdaQueryWrapper<DeviceAccessVisitor>()
                    .eq(DeviceAccessVisitor::getIpAddress, ipAddress)
                    .eq(DeviceAccessVisitor::getAccessCode, accessCode).eq(DeviceAccessVisitor::getType, visitor.getType()).eq(DeviceAccessVisitor::getOnlineFlag, "1"));
        }


        if(!CollectionUtils.isEmpty(list)){
            Long baseId = list.get(0).getBaseId();
            Date beginTime = list.get(0).getBeginTime();
            visitor.setBaseId(baseId);
            Date endTime = new Date();
            visitor.setEndTime(endTime);
            Duration duration = Duration.ofMillis(endTime.getTime() - beginTime.getTime());
            long seconds = duration.getSeconds();
            visitor.setAccessInterval(seconds);
            visitor.setUpdateTime(endTime);
            return deviceAccessVisitorMapper.updateById(visitor);
        }else{
            if(visitor.getErrorPlayFlag() != null && visitor.getErrorPlayFlag()){
                return 0;
            }
            if("0".equals(visitor.getOnlineFlag())){
                return 0;
            }
            Date now = new Date();
            visitor.setBeginTime(now);
            visitor.setAccessInterval(0L);
            visitor.setCreateTime(now);
            if("0".equals(visitor.getType())){
                MonitorArea area = areaService.getById(deviceId);
                String baseName = area.getBaseName();
                String ancestors = area.getAncestors();
                List<String> ancestorList = Arrays.stream(ancestors.split(",")).collect(Collectors.toList());
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < ancestorList.size() ; i++){
                    String ancestor = ancestorList.get(i);
                    if(!"0".equals(ancestor)){
                        MonitorArea monitorArea = areaService.getById(Long.parseLong(ancestor));
                        sb.append(monitorArea.getBaseName()).append("-");
                    }
                }
                sb.append(baseName);
                visitor.setDeviceName(sb.toString());
            }
            return deviceAccessVisitorMapper.insert(visitor);
        }

    }

    @Override
    public int deleteByIds(List<Long> ids) {
        return deviceAccessVisitorMapper.deleteBatchIds(ids);
    }

    @Override
    public Map visitorCount() {
        return deviceAccessVisitorMapper.visitorCount();
    }

    @Override
    public List<Map> deviceCount() {
        return deviceAccessVisitorMapper.deviceCount();
    }

    @Override
    public List<Map> deviceAccessInterval() {
        return deviceAccessVisitorMapper.deviceAccessInterval();
    }

    @Override
    public List<Map> deviceAccessTrend(DeviceAccessVisitorDto dto) {
        return deviceAccessVisitorMapper.deviceAccessTrend(dto);
    }
}